﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using YougeBookmark.Data;
using YougeBookmark.Models;
using YougeBookmark.Utilities;
using Microsoft.EntityFrameworkCore;

namespace YougeBookmark.Services
{
    public class TagManager
    {
        private readonly TagRepository _tagRepo;
        private readonly BookmarkTagRepository _bookmarkTagRepo;
        private readonly Logger _logger;

        public TagManager(
            TagRepository tagRepository,
            BookmarkTagRepository bookmarkTagRepo,
            Logger logger)
        {
            _tagRepo = tagRepository ?? throw new ArgumentNullException(nameof(tagRepository));
            _bookmarkTagRepo = bookmarkTagRepo ?? throw new ArgumentNullException(nameof(bookmarkTagRepo));
            _logger = logger ?? throw new ArgumentNullException(nameof(logger));
        }

        /// <summary>
        /// 创建新标签（自动校验唯一性）
        /// </summary>
        public async Task<Tag> CreateTagAsync(string tagName)
        {
            using var transaction = _tagRepo.BeginTransaction();
            try
            {
                if (await _tagRepo.CheckNameExistsAsync(tagName))
                {
                    _logger.Warn($"标签名称已存在: {tagName}");
                    return null;
                }

                var newTag = new Tag { Name = tagName.Trim() };
                var created = await _tagRepo.AddAsync(newTag.Name);
                transaction.Commit();
                return created;
            }
            catch (Exception ex)
            {
                transaction.Rollback();
                _logger.Error($"标签创建失败: {ex.Message}", ex);
                throw;
            }
        }

        /// <summary>
        /// 安全删除标签（级联删除关联关系）
        /// </summary>
        public async Task<bool> DeleteTagAsync(int tagId)
        {
            using var transaction = _tagRepo.BeginTransaction();
            try
            {
                // 删除所有关联的书签关系
                var deleteCount = await _bookmarkTagRepo.DeleteByTagAsync(tagId);
                _logger.Info($"已清理{deleteCount}条书签关联");

                // 删除标签本体
                var result = await _tagRepo.DeleteAsync(tagId);
                transaction.Commit();
                return result;
            }
            catch (Exception ex)
            {
                transaction.Rollback();
                _logger.Error($"标签删除失败: {ex.Message}", ex);
                throw;
            }

            //// 先删除关联关系
            //await _bookmarkTagRepo.DeleteByTagAsync(tagId);

            //// 再删除标签
            //return await _tagRepo.DeleteAsync(tagId);
        }

        /// <summary>
        /// 更新标签名称（支持合并重复标签）
        /// </summary>
        public async Task<Tag> UpdateTagAsync(int tagId, string newName)
        {
            using var transaction = _tagRepo.BeginTransaction();
            try
            {
                // 检查是否存在同名标签
                var existingTag = await _tagRepo.GetByNameAsync(newName);
                if (existingTag != null)
                {
                    await MergeTagsAsync(existingTag.Id, new[] { tagId });
                    transaction.Commit();
                    return existingTag;
                }

                // 无重复则直接更新
                var updated = await _tagRepo.UpdateAsync(tagId, newName);
                transaction.Commit();
                return updated;
            }
            catch (Exception ex)
            {
                transaction.Rollback();
                _logger.Error($"标签更新失败: {ex.Message}", ex);
                throw;
            }
        }

        /// <summary>
        /// 分页获取标签列表（带使用量统计）
        /// </summary>
        public async Task<(List<TagInfo> Tags, int TotalCount)> GetPagedTagsAsync(int pageIndex, int pageSize)
        {
            try
            {
                var query = _tagRepo.GetAll()
                    .Select(t => new TagInfo
                    {
                        Tag = t,
                        UsageCount = t.BookmarkTags.Count
                    });

                var total = await query.CountAsync();
                var items = await query
                    .OrderByDescending(t => t.UsageCount)
                    .ThenBy(t => t.Tag.Name)
                    .Skip(pageIndex * pageSize)
                    .Take(pageSize)
                    .AsNoTracking()
                    .ToListAsync();

                return (items, total);
            }
            catch (Exception ex)
            {
                _logger.Error($"标签分页查询失败: {ex.Message}", ex);
                throw;
            }
        }

        /// <summary>
        /// 合并多个标签到目标标签（原子操作）
        /// </summary>
        public async Task<Tag> MergeTagsAsync(int targetTagId, IEnumerable<int> sourceTagIds)
        {
            using var transaction = _tagRepo.BeginTransaction();
            try
            {
                var targetTag = await _tagRepo.GetByIdAsync(targetTagId);
                if (targetTag == null) throw new KeyNotFoundException("目标标签不存在");

                foreach (var sourceTagId in sourceTagIds.Distinct())
                {
                    if (sourceTagId == targetTagId) continue;

                    // 转移关联关系到目标标签
                    var associations = await _bookmarkTagRepo.GetByTagAsync(sourceTagId);
                    foreach (var bt in associations)
                    {
                        await _bookmarkTagRepo.CreateAssociationAsync(bt.BookmarkId, targetTagId);
                    }

                    // 删除源标签
                    await _tagRepo.DeleteAsync(sourceTagId);
                }

                transaction.Commit();
                return targetTag;
            }
            catch (Exception ex)
            {
                transaction.Rollback();
                _logger.Error($"标签合并失败: {ex.Message}", ex);
                throw;
            }
        }

        /// <summary>
        /// 为书签批量更新标签（智能处理新增/删除）
        /// </summary>
        public async Task UpdateBookmarkTagsAsync(int bookmarkId, IEnumerable<string> tags)
        {
            using var transaction = _tagRepo.BeginTransaction();
            try
            {
                // 获取现有关联
                var existingTagIds = (await _bookmarkTagRepo.GetTagIdsByBookmarkAsync(bookmarkId))
                    .ToHashSet();

                // 处理新标签
                var newTags = await ProcessTagCollectionAsync(tags);
                var newTagIds = newTags.Select(t => t.Id).ToHashSet();

                // 计算需要删除的标签
                var toRemoveIds = existingTagIds.Except(newTagIds).ToList();
                foreach (var tagId in toRemoveIds)
                {
                    await _bookmarkTagRepo.DeleteAsync(bookmarkId, tagId);
                }

                // 添加新关联
                var toAddIds = newTagIds.Except(existingTagIds).ToList();
                foreach (var tagId in toAddIds)
                {
                    await _bookmarkTagRepo.AddAsync(bookmarkId, tagId);
                }

                transaction.Commit();
            }
            catch (Exception ex)
            {
                transaction.Rollback();
                _logger.Error($"书签标签更新失败: {ex.Message}", ex);
                throw;
            }
        }

        /// <summary>
        /// 处理标签集合（自动去重并创建新标签）
        /// </summary>
        private async Task<List<Tag>> ProcessTagCollectionAsync(IEnumerable<string> tagNames)
        {
            var normalizedNames = tagNames
                .Where(n => !string.IsNullOrWhiteSpace(n))
                .Select(n => n.Trim())
                .Distinct()
                .ToList();

            var tags = new List<Tag>();
            foreach (var name in normalizedNames)
            {
                var tag = await _tagRepo.GetByNameAsync(name) ?? await CreateTagAsync(name);
                if (tag != null) tags.Add(tag);
            }
            return tags;
        }
    }

    public class TagInfo
    {
        public Tag Tag { get; set; }
        public int UsageCount { get; set; }
    }
}